package edu.java.texbooks.tutorial.test05.collections.list;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;

public class Test {
	static String number01 = "1";
	static String number02 = "2";
	static String number03 = "3";
	static String number04 = "4";
	static String number05 = "5";

	static String number06 = "6";

	public static void main(String[] args) {
		List<String> myList = new ArrayList<String>();
		myList.add(number01);
		myList.add(number02);
		myList.add(number03);
		myList.add(number04);

		System.out.println("\n" + "------- Print ArrayList ----------");
		System.out.println(myList);

		swap(myList, 0, myList.size() - 1);
		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println(myList);

		// shuffle the list
		swap(myList, 0, myList.size() - 1);
		myList.add(number05);

		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println(myList);

		myShuffle(myList);
		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println("My Shuffle:\t" + myList);

		Collections.sort(myList);
		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println(myList);

		// test 1
		// Random random=new Random();
		// Collections.shuffle(myList, random);

		// test2
		Collections.shuffle(myList);

		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println("Collections Shuffle: " + myList);

		// clear myList, create Array, use atList() method and fill again myList
		System.out.println("\n----------------------------------\n");
		System.out.println("clear myList, create Array, "
				+ "use atList() method and fill again myList");
		myList.clear();
		String[] myString = { number01, number02, number03, number04, number05 };
		List<String> sharedList = Arrays.asList(myString);

		System.out.println("\n\n" + "------- Print ArrayList ----------");
		System.out.println(sharedList);

		myList.clear();
		myList.add(number01);
		myList.add(number02);
		myList.add(number03);
		myList.add(number04);
		System.out.println("\n----------------\n");
		System.out.println(myList);
		System.out.println("size: " + myList.size());

		System.out.println("------------ Test ListIterator ----------------");

		ListIterator<String> iterator = myList.listIterator();
		System.out.println("iterator:  " + iterator);

		while (iterator.hasPrevious()) {
			System.out.println("Get the beginning of List.");
		}

		while (iterator.hasNext()) {
			String number = iterator.next();
			System.out.println("number[ " + iterator.previousIndex() + " ]="
					+ number);
		}
		System.out.println(iterator.nextIndex());

		System.out.println("\n-----------------------\n");
		iterator = myList.listIterator(myList.size());
		while (iterator.hasPrevious()) {
			System.out.println("number[" + (iterator.previousIndex()) + "]= "
					+ iterator.previous());
		}

		System.out.println("--------------------");
		for (iterator = myList.listIterator(myList.size()); iterator
				.hasPrevious();) {
			System.out.print(" " + iterator.previous());
		}
		System.out.println("\n--------------------\n");

		iterator = myList.listIterator(1);
		// iterator.set(number05);
		System.out.println(iterator.next());
		// System.out.println(iterator.previous());
		System.out.println("\n" + myList);

		iterator.add(number05);
		iterator.next();
		// before set() method we must call next() or previous() method
		iterator.set(number01);
		iterator = myList.listIterator(myList.size());
		System.out.println("\n" + myList);

		iterator.previous();
		// before remove() method we must call next() or previous() method
		iterator.remove();
		System.out.println("\n" + myList);

		iterator = myList.listIterator(myList.size() - 1);
		System.out.println(iterator.next());

		iterator = myList.listIterator(1);
		System.out.println("Put iterator on argument with index " + 1);
		String numb1 = iterator.next();
		String numb2 = iterator.previous();

		System.out.println("iterator.next()= " + numb1);
		System.out.println("iterator.previous()= " + numb2);

		System.out.println("\n--------------------\n");
		iterator = myList.listIterator(1);
		System.out.println("Put iterator on argument with index " + 1);
		numb1 = iterator.previous();
		numb2 = iterator.next();

		System.out.println("iterator.previous()= " + numb1);
		System.out.println("iterator.next()= " + numb2);

		System.out.println("\n--------------------\n");
		System.out.println(myList);

		List<String> subList = myList.subList(0, 3);
		// the sublist which we get shares its elements with the myList. So if
		// we change some of them it will reflect to the other.
		System.out.println(subList);

		// test 1
		// subList.clear();
		// System.out.println(myList);

		// test 2

		// test 2.1
		// error --> you can't add element in the range of the subList because
		// it will reflect to subList, but range of sublist is fixed
		// myList.add(1, number06);

		// test 2.2
		// we set an element in myList which is in the range of the subList.
		// So the changes also will reflect in the subList
		// myList.set(1, number06);

		// test 2.3
		// we set an element in myList which is out of subList's range
		myList.set(3, number06);

		System.out.println("subList: " + subList);
		System.out.println("myList: " + myList);

		// searching an element in sublist
		myList.add(number02);
		myList.add(number03);
		myList.add(number05);
		myList.add(number03);
		myList.add(number06);

		System.out.println("\n--------------------\n");
		System.out.println(myList);
		List<String> subList2 = myList.subList(3, myList.size());

		System.out.println("sublist:  " + subList2);
		int indexInSublist = subList2.indexOf(number03);
		System.out.println("index of element " + number03 + " in subList: "
				+ indexInSublist);

		System.out.println("\n--------------------\n");
		List<String> subList3 = new ArrayList<String>(subList2);
		System.out.println("myList: " + myList);
		System.out.println("subList2: " + subList2);
		System.out.println("subList3: " + subList3);

		subList3.remove(number06);
		subList2.clear();
		System.out.println("-----------------------");
		System.out.println("myList: " + myList);
		System.out.println("subList2: " + subList2);
		System.out.println("subList3: " + subList3);

		System.out.println("\n-----------------------");
		myList.clear();
		myList.add(number01);
		myList.add(number02);
		myList.add(number03);
		myList.add(number04);
		myList.add(number05);
		myList.add(number06);
		System.out.println("myList before rotation: " + myList);
		Collections.rotate(myList, myList.size());
		System.out.println("myList after rotation: " + myList);

		// swap the first and the last element in the list
		Collections.swap(myList, 0, myList.size() - 1);
		// Collections.swap(myList, 0, myList.size() - 1);
		System.out.println("\n-------- swapping --------");
		System.out.println("myList after swapping: " + myList);

		Collections.sort(myList);
		System.out.println("myList after sorting: " + myList);
		ListIterator<String> iterator2 = myList.listIterator(myList.size());
		for (iterator = myList.listIterator(); (iterator.nextIndex()) <= (myList
				.size() / 2); iterator.next(), iterator2.previous()) {
			Collections.swap(myList, iterator.nextIndex(), iterator2
					.previousIndex());
			System.out.println(myList);
		}
		System.out.println("myList after swapping: " + myList);
		Collections.sort(myList);
		System.out.println("natural order:\t\t" + myList);
		Collections.reverse(myList);
		System.out.println("reversed natural order:\t" + myList);

		System.out.println("\n-----------------------\n");
		Collections.sort(myList);
		myList.add(number02);
		myList.add(number03);
		myList.add(number02);
		System.out.println("myList: " + myList);
		Collections.replaceAll(myList, number02, "7");
		System.out.println("myList after replacing: " + myList);
		Collections.replaceAll(myList, "7", number02);

		System.out.println("myList: " + myList);
		List<String> subList4 = myList.subList(3, myList.size());
		List<String> copyOfSubList = new ArrayList<String>(subList4);
		Collections.fill(subList4, "7");
		System.out.println("myList after filling: " + myList);
		subList4.clear();
		subList4 = new ArrayList<String>(copyOfSubList);
		System.out.println("myList in natural view: " + myList);

		System.out.println("\n-----------------------\n");
		List<String> list01 = new ArrayList<String>();
		list01.add(number01);
		list01.add(number02);
		list01.add(number03);

		List<String> list02 = new ArrayList<String>();
		// list02.add(number01);
		// list02.add(number02);
		list02.add(number03);
		list02.add(number04);
		list02.add(number05);

		System.out.println("List01: " + list01);
		System.out.println("List02: " + list02);
		// when we copy lists they must be with equal size
		Collections.copy(list01, list02);
		System.out.println("\n----------------------\n");
		System.out.println("List01: " + list01);
		System.out.println("List02: " + list02);

		System.out.println("\n----------------------\n");
		System.out.println(myList);
		String[] addNumbersArray = { number06, number04, number02, number05,
				number01 };
		myList.addAll(Arrays.asList(addNumbersArray));
		System.out.println(myList);

		Collections.sort(myList);
		// before searching the collection must be ordered
		int searchIndex = Collections.binarySearch(myList, number05);
		System.out.println("number " + number05 + " on index: " + searchIndex);

		System.out.println("\n----------------------\n");
		myList.add(3, number05);
		myList.add(7, number02);
		myList.add(number06);
		List<String> subList5 = new ArrayList<String>();
		subList5.add(number02);
		subList5.add(number05);

		myList.addAll(subList5);
		System.out.println("subList: " + subList5);
		System.out.println("myList: " + myList);

		int firstIndexSubList = Collections.indexOfSubList(myList, subList5);
		int lastIndexSubList = Collections.lastIndexOfSubList(myList, subList5);
		System.out.println("Index of first appearing of the subList: "
				+ firstIndexSubList);
		System.out.println("Index of last appearing of the subList: "
				+ lastIndexSubList);

		

	}

	public static void swap(List<String> list, int i, int j) {
		String tempPerson = list.get(i);
		list.set(i, list.get(j));
		list.set(j, tempPerson);
	}

	public static void myShuffle(List<String> list) {
		Random random = new Random();

		for (int i = list.size(); i > 1; i--) {
			swap(list, i - 1, random.nextInt(i));
		}
	}

}
